const myCall = function (context) {
  if(typeof this !== 'function') {
    throw new TypeError('error')
  }
  context = context || window

  const fn = Symbol()
  context[fn] = this
  const args = [...arguments].slice(1)
  const result = context[fn](...args)
  delete context[fn]
  return result
}

const myApply = function (context) {
  const fn = Symbol()
  context[fn] = this
  let result
  if(arguments[1]) {
    result = context[fn](...arguments[1])
  } else {
    result = context[fn]()
  }
  return result
}

const myBind = function (context) {
  if(typeof this !== 'function') {
    throw new TypeError('error')
  }
  const _this = this
  const args = [...arguments].slice(1)
  return function F() {
    if(this instanceof F) {
      return new _this(...args, ...arguments)
    }
    return _this.apply(context, args.concat(...arguments))
  }
}

const myNew = function (fn, ...args) {
  const obj = Object.create(fn.prototype)
  const result = fn.apply(obj, args)
  return result instanceof Object ? result : obj
}
